package net.ib.mtalk.sync;

import net.ib.mtalk.database.DatabaseContract.ContactTable;
import net.ib.mtalk.global.GlobalApplication;
import net.ib.mtalk.util.MTalkLogWriter;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.database.CursorJoiner;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.RawContacts;

/**
 * Contact 과 Application 이 지니고 있는 폰 북을 비교하는 작업들을 수행하는 class 이다.
 * @author namkhoh
 *
 */
public class ContactComparator {
	
	private static final String TAG		=	"ContactComparator";

	/**
	 * 전체 PhoneBook 의 version 의 합계를 저장하고 있다.
	 * 해당 version 합계는 deleted 까지 포함하여 저장한다. 
	 * @return
	 */
	public static int checkContactVersion() {
		// 필요한 columns
		String[] projection = {ContactsContract.RawContacts._ID, ContactsContract.RawContacts.VERSION};
//		String selection = ContactsContract.RawContacts.ACCOUNT_TYPE + " != '" + MTalkConstant.ACCOUNT_TYPE +"'";
		
		Context mContext = GlobalApplication.getContext();
		Cursor cCursor = mContext.getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI, projection, null, null, null);
		int versionSum = 0;
		try{
			while (cCursor.moveToNext()) {
				versionSum += cCursor.getInt(cCursor.getColumnIndexOrThrow(RawContacts.VERSION));
			}
		} finally {
			cCursor.close();
		}
		return versionSum;
	}
	
	public interface ContactChangeAction {
		public void onNumberInserted(Cursor contact, Cursor app);
		public void onNumberDeleted(Cursor contact, Cursor app);
		public void onNumberChanged(Cursor contact, Cursor app);
		public void onNameChanged(Cursor contact, Cursor app);
	}
	
	/**
	 * 기존에 App 에 저장된 Phone book data 와 현재 Contacts 에 있는 data 를 compare 한다. 
	 * 
	 * @param newEntry		새롭게 생성된 array 를 넣어주면 추가된 data 를 담아준다.
	 * @param deletedEntry	새롭게 생성된 array 를 넣어주면 삭제된 data 를 담아준다.
	 */
	public static void compareNumber(ContactChangeAction changeAction) {
		Context mContext = GlobalApplication.getContext();
		ContentResolver mResolver = mContext.getContentResolver();
				
		// PhoneBook 에서 필요한 columns
		String[] projectionContact = {	ContactsContract.CommonDataKinds.Phone.NUMBER,
										ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID,
										ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
										ContactsContract.CommonDataKinds.Phone.DATA_VERSION};
		
		Cursor cCursor = mResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projectionContact, null, null, ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID);
		

		// ChatON table 에서 필요한 columns
		String[] projectionMTalk = {ContactTable.KEY_CONTACT_NUMBER,
									ContactTable.KEY_CONTACT_PHONE_ID,
									ContactTable.KEY_CONTACT_NAME,
									ContactTable.KEY_CONTACT_VERSION
									};
		
		Cursor mCursor = mResolver.query(ContactTable.CONTENT_URI, projectionMTalk, null, null, ContactTable.KEY_CONTACT_PHONE_ID);

		// 두개의 Cursor 를 Join 한다 by _id
		CursorJoiner joiner = new CursorJoiner(cCursor, new String[]{ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID}, mCursor, new String[]{ContactTable.KEY_CONTACT_PHONE_ID});
		
		for (CursorJoiner.Result joinerResult : joiner) {
			switch (joinerResult) {
			case LEFT:
				// Phone Book 에서 추가
				MTalkLogWriter.i("Added : " + cCursor.getString(cCursor.getColumnIndexOrThrow(Phone.NUMBER)));
				changeAction.onNumberInserted(cCursor, mCursor);
				break;
			case RIGHT:
				// PhoneBook 에서 삭제
				MTalkLogWriter.i("Deleted : " + cCursor.getString(cCursor.getColumnIndexOrThrow(Phone.NUMBER)));
				changeAction.onNumberDeleted(cCursor, mCursor);
				break;
			case BOTH:
				int contactVersion = cCursor.getInt(cCursor.getColumnIndexOrThrow(Phone.DATA_VERSION));
	        	int appVersion = mCursor.getInt(mCursor.getColumnIndexOrThrow(ContactTable.KEY_CONTACT_VERSION));
	        	if (contactVersion != appVersion) {
	        		 String numberInPno = cCursor.getString(0);
	        		 String numberInApp = mCursor.getString(0);
	        		 if (!numberInPno.equals(numberInApp)) {
	        			 // Phonebook 에서 변경
	        			 MTalkLogWriter.i("Number Modified,  " + numberInApp + " -> " + numberInPno);
	        			 changeAction.onNumberChanged(cCursor, mCursor);
	        		 }
	        		 String nameInContact = cCursor.getString(2);
	        		 String nameInApp = cCursor.getString(2);
	        		 if (!nameInContact.equals(nameInApp)) {
	        			 MTalkLogWriter.i("Name Modified,  " + nameInApp + " -> " + nameInContact);
	        			 changeAction.onNameChanged(cCursor, mCursor);
	        		 }
	        	}
				break;
			}
		}
		
		cCursor.close();
		mCursor.close();
	}
}
